package com.example.wcdb.config;

import android.app.Application;
import android.os.Handler;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteDatabase;

import com.example.wcdb.RepairableDatabase;
import com.example.wcdb.config.exception.CorruptExceptionHandler;
import com.example.wcdb.config.database.WCDBDatabase;
import com.example.wcdb.config.database.WCDBOpenHelperFactory;
import com.tencent.wcdb.DatabaseErrorHandler;
import com.tencent.wcdb.database.SQLiteCipherSpec;
import com.tencent.wcdb.database.SQLiteDatabase;
import com.tencent.wcdb.database.SQLiteDatabaseCorruptException;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 数据库构建帮助类，将各种预置参数放到该类中，减少{@link RepairableDatabase}类中的逻辑代码
 * @author zhangxin221
 */
public class DbHelper {
    public static final String TAG = DbHelper.class.getName();
    public static final RoomDatabase.Callback ROOM_DATABASE_CALLBACK = new RoomDatabase.Callback() {
        @Override
        public void onCreate(@NonNull SupportSQLiteDatabase db) {
            super.onCreate(db);
            checkIsInit();
            RepairableDatabase.getDatabase().saveMaster(new RepairableDatabase.OperateCallback() {
                @Override
                public void onSuccess() {
                    Log.d(TAG, "创建时备份成功");
                }

                @Override
                public void onError(String errMsg) {
                    Log.d(TAG, "创建时备份失败，" + errMsg);
                }

                @Override
                public void onCancel() {
                    Log.d(TAG, "创建时备份取消");
                }
            });
        }
    };
    public static final DatabaseErrorHandler ERROR_HANDLER = dbObj -> {
        // Do nothing
        // 不设置的话，数据库在打开时报错会自动删除报错数据库文件，导致无法进行后续修复
    };
    public static WCDBOpenHelperFactory mFactory = null;

    public static final SQLiteCipherSpec SQLITE_CIPHER_SPEC = new SQLiteCipherSpec()
            .setPageSize(1024).setKDFIteration(64000);
    public static final int LIMIT_QUEUE_SIZE = 1000;
    public static final ThreadPoolExecutor SINGLE_THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
            1, 1, 0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(LIMIT_QUEUE_SIZE), new ThreadPoolExecutor.CallerRunsPolicy());
    public static Handler mUiHandler;
    public static Application mApplication;
    public static DbConfig mDbConfig;
    private static boolean initFlag = false;

    public static void init(Application application, DbConfig dbConfig) {
        initFlag = true;
        mApplication = application;
        mDbConfig = dbConfig;
        mUiHandler = new Handler(application.getMainLooper());
        mFactory = new WCDBOpenHelperFactory()
                .passphrase(mDbConfig.getDbPassword())  // passphrase to the database, remove this line for plain-text
                .cipherSpec(SQLITE_CIPHER_SPEC)       // cipher to use, remove for default settings
                .writeAheadLoggingEnabled(true)         // enable WAL mode, remove if not needed
                .asyncCheckpointEnabled(true);
        //启动定期备份后台服务
        BackupHelper.startBackupService(application);
        CorruptExceptionHandler.getInstance().setCorruptListener(dbConfig.getCorruptListener());
    }

    public static void checkIsInit() {
        if (!initFlag) {
            throw new IllegalStateException("请先调用init方法进行初始化！！");
        }
    }

    public static void checkIsCorrupted() {
        //先关闭原来的连接
        RepairableDatabase.getDatabase().getOpenHelper().close();
        //重置实例，重新尝试open
        RepairableDatabase.getDatabase().resetInstance();
        SQLiteDatabase db = RepairableDatabase.getDatabase().getWcdbSqlite();
        db.execSQL("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name='room_master_table'");

    }

    public static void runOnUiThread(Runnable runnable) {
        mUiHandler.post(runnable);
    }

    /**
     * 获取系统数据库路径
     * @param dbName 数据库名称
     * @return 数据库路径
     */
    public static File getDbPath(String dbName) {
        return mApplication.getDatabasePath(dbName);
    }

    /**
     * 获取MasterInfo的备份路径
     * @param database 数据库实例，用于获取系统数据库路径
     * @return MasterInfo的备份路径
     */
    public static String getMasterInfoSavePath(File database) {
        return database.getPath() + "-mbak";
    }

    /**
     * 获取数据库备份路径
     * @param database 数据库实例，用于获取系统数据库路径
     * @return 数据库的备份路径
     */
    public static String getBackupPath(File database) {
        return database.getPath() + "-backup";
    }



}
